package main

import (
	"time"
	"context"
	"go.mongodb.org/mongo-driver/mongo"
	"go.mongodb.org/mongo-driver/mongo/options"
	"log"
	"go.mongodb.org/mongo-driver/bson"
)

type User struct {
	Id int
	Name string
	Age  int
	City string
}


func main() {
    //上下文
	ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
	defer cancel()
    // client
	uri := "mongodb://192.168.0.203:27007,192.168.0.203:27017"
	client, err := mongo.Connect(ctx, options.Client().ApplyURI(uri))
	if err != nil{
		log.Fatal(err)
	}
	// 检查链接
	err = client.Ping(ctx, nil)
	if err != nil {
		log.Fatal(err)
	}
	log.Println("Connected to MongoDB!")
    //关闭 client
	defer client.Disconnect(ctx)
	//打开 collection
	collection := client.Database("test").Collection("user")

	user1 := User{1,"luo",10,"gz"}
	user2 := User{2,"luo",10,"gz"}
	user3 := User{3,"luo",10,"gz"}
	// 添加
	insertResult, err := collection.InsertOne(ctx, user1)
	if err != nil {
		log.Fatal(err)
	}
	log.Println("Inserted a single document: ", insertResult.InsertedID)
	//批量添加
	temps := []interface{}{user2, user3}
	insertManyResult, err := collection.InsertMany(ctx, temps)
	if err != nil {
		log.Fatal(err)
	}
	log.Println("Inserted multiple documents: ", insertManyResult.InsertedIDs)

	// filter
	upFilter := bson.D{{"id",1}}
	// 更新
	update := bson.D{
		{"$set", bson.D{
			{"age", 4},
		}},
	}
	//updateResult, err := collection.UpdateOne(ctx, upFilter, update) //单个更新
	updateResult, err := collection.UpdateMany(ctx, upFilter, update)  //多个更新
	if err != nil {
		log.Fatal(err)
	}
	log.Printf("Matched %v documents and updated %v documents.\n", updateResult.MatchedCount, updateResult.ModifiedCount)

	//find one
	var result User

	filter := bson.D{}
	e := bson.E{}
	e.Key = "id"
	e.Value = 1
	filter = append(filter,e)

	err = collection.FindOne(ctx, filter).Decode(&result)
	if err != nil {
		log.Fatal(err)
	}
	log.Printf("Found a single document: %+v\n", result)

	// find more
	findOptions := options.Find()
	findOptions.SetSkip(0)
	findOptions.SetLimit(2)
	// 查询条件
	findFilter := bson.D{}
	// 查询结果
	var results []User
	// 过滤器匹配集合中的所有文档
	cur, err := collection.Find(ctx, findFilter, findOptions)
	if err != nil {
		log.Fatal(err)
	}
	// 查找多个文档会返回一个游标，通过游标迭代可以让一次解码一个文档
	for cur.Next(ctx) {
		// 创建一个可以解码单个文档的值
		var elem User
		err := cur.Decode(&elem)
		if err != nil {
			log.Fatal(err)
		}
		results = append(results, elem)
	}

	if err := cur.Err(); err != nil {
		log.Fatal(err)
	}
	// 完成后关闭光标
	cur.Close(ctx)
	log.Printf("Found multiple documents (array of pointers): %+v\n", results)
    //总数
	count, err := collection.CountDocuments(ctx, findFilter)
	if err != nil {
		log.Fatal(err)
	}
	log.Printf("Document count : %d\n",count)

	//删除
	delFilter := bson.D{{"id", 1}}
	deleteResult, err := collection.DeleteMany(ctx, delFilter)
	if err != nil {
		log.Fatal(err)
	}
	log.Printf("Deleted %v documents in the trainers collection\n", deleteResult.DeletedCount)
}
